package model.interfaces;


import java.util.Iterator;
import java.util.LinkedList;

import model.LeafNode;
import model.exceptions.NoObjectivesException;
import model.exceptions.NoTreesException;


public abstract class Session {
	protected LinkedList<Node> treeList = new LinkedList<Node>();
	protected LinkedList<Objective> objectiveList = new LinkedList<Objective>();
	protected LinkedList<Object> objects = new LinkedList<Object>();
	
	/**
	 * Method to be redifined deppending on the execution type.
	 * This base implementation checks which objectives where
	 * achieved and executes them.
	 * @throws NoObjectivesException 
	 * @throws NoTreesException 
	 */
	public void verifyRules() throws NoObjectivesException, NoTreesException{
		if (objectiveList.isEmpty()) {
			throw new NoObjectivesException();
		}else if(this.treeList.isEmpty()){
			throw new NoTreesException();
		}
	}
	
	public void addDependencyTree(Node root){
		this.treeList.add(root);
	}
	
	public void addObjective(Objective objective) {
		this.objectiveList.add(objective);
	}
	
	public void addObject(Object object) {
		this.objects.add(object);
	}
	
	public void resetObjects() {
		this.objects.clear();
	}
	
	public void resetObjectives() {
		this.objectiveList.clear();
	}
	
	/**
	 * Method that clears the objects and objectives that where added.
	 */
	public void resetSession() {
		this.resetObjectives();
		this.resetObjects();
	}
	
	/*Add the object till the first not verified objective*/
	protected void doAddObject(Object object, Rule rule){
		rule.addObject(object);
	}
	
	/*Reset all the rules in the objective for the next run*/
	protected void clearObjective(LinkedList<Rule> rulesList){
		Iterator<Rule> it = rulesList.iterator();
		while(it.hasNext()){
			it.next().reset();
		}
	}
	
	protected LinkedList<Rule> getRulesList(Objective objective){
		LinkedList<Rule> rulesList = new LinkedList<Rule>();
		this.addRule(objective.getObjective(), rulesList);
		return rulesList;
	}
	
	protected void addRule(Node node, LinkedList<Rule> rulesList){
		if(node instanceof LeafNode){
			LeafNode leaf = (LeafNode) node;
			rulesList.add(leaf.getRule());
		}else{
			if(node.hasChildren()){
				CompositeNode nodeAux = (CompositeNode) node;
				Iterator<Node> it = nodeAux.getChildren().iterator();
				while(it.hasNext())
					addRule(it.next(),rulesList);
			}
		}
	}
}
